package com.open.capacity.reimburse.controller;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import com.open.capacity.annotation.log.LogAnnotation;
import com.open.capacity.common.FileService;
import com.open.capacity.commons.Result;
import com.open.capacity.model.system.LoginAppUser;
import com.open.capacity.model.system.SysUser;
import com.open.capacity.reimburse.dto.FileAuthProcessDto;
import com.open.capacity.reimburse.entity.BaseCar;
import com.open.capacity.reimburse.entity.SysFilefolder;
import com.open.capacity.reimburse.entity.SysFileinfoAuthorize;
import com.open.capacity.reimburse.service.SysFilefolderService;
import com.open.capacity.reimburse.service.SysFileinfoAuthorizeService;
import com.open.capacity.user.model.SysFile;
import com.open.capacity.user.service.SysFileService;
import com.open.capacity.utils.DateUtil;
import com.open.capacity.utils.SysUserUtil;
import com.open.capacity.utils.file.FileUtils;
import com.open.capacity.workflow.model.WFProcessinstance;
import com.open.capacity.workflow.service.WFProcessinstanceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.access.prepost.PreAuthorize;
import com.open.capacity.reimburse.entity.SysFileinfo;
import com.open.capacity.reimburse.service.SysFileinfoService;

import com.open.capacity.commons.PageResult;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

/**
 * 文件信息
 *
 * @author
 * @email
 * @date 2021-02-07 10:00:46
 */
@Slf4j
@RestController
@RequestMapping("fileinfos")
@Api(tags = "文件信息")
public class SysFileinfoController {

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private SysFileinfoService sysFileinfoService;

    @Autowired
    private SysFilefolderService sysFilefolderService;

    @Autowired
    private SysFileinfoAuthorizeService sysFileinfoAuthorizeService;

    @Autowired
    private WFProcessinstanceService processinstanceService;

    @Value("${file.uploadpath:/usr/local/files/upload}")
    private String fileuploadPath;

    /**
     * 全部列表
     */
    @RequestMapping("/list")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:list')")
    public Result list(@RequestParam Map<String, Object> params) {
        SysUser loginUser = SysUserUtil.getLoginAppUser();
        params.put("createUserid", loginUser.getId());
        params.put("status", 1);
        if (params.containsKey("folderId") && StringUtils.isNotEmpty(params.get("folderId").toString())) {
            if (params.get("folderId").toString().equals("0")) {
                params.put("folderId", "");
            }
        } else {
            params.put("folderId", "");
        }
        List<SysFileinfo> fileList = sysFileinfoService.findAll(params);
        if (params.containsKey("folderId") && StringUtils.isNotEmpty(params.get("folderId").toString())) {
            params.put("parentId", params.get("folderId"));
            if (params.get("folderId").toString().equals("0")) {
                params.put("parentId", "");
            }
        } else {
            params.put("parentId", "");
        }
        List<SysFilefolder> folderList = sysFilefolderService.findAll(params);
        if (CollectionUtils.isNotEmpty(folderList)) {
            fileList.addAll(folderList.stream().map(item ->
                    {
                        SysFileinfo a = new SysFileinfo();
                        a.setAuthType("");
                        BeanUtils.copyProperties(item, a);
                        return a;
                    }
            ).collect(Collectors.toList()));
        }
        return Result.succeed(fileList);
    }

    /**
     * top5
     */
    @RequestMapping("/top5")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:list')")
    public Result top5(@RequestParam Map<String, Object> params) {
        SysUser loginUser = SysUserUtil.getLoginAppUser();
        params.put("createUserid", loginUser.getId());
        params.put("status", 1);
        List<SysFileinfo> fileList = sysFileinfoService.findTop5(params);
        return Result.succeed(fileList);
    }

    /**
     * 文档列表
     */
    @RequestMapping("/documentList")
    @PreAuthorize("hasAnyAuthority('sys_filefolder:sysfilefolder:list')")
    public Result documentList(@RequestParam Map<String, Object> params) {
        SysUser loginUser = SysUserUtil.getLoginAppUser();
        params.put("createUserid", loginUser.getId());
        params.put("status", 1);
        params.put("exts", Arrays.asList("xlsx", "xls", "doc", "docx", "ppt", "pptx", "pdf", "txt"));
        List<SysFileinfo> list = sysFileinfoService.findAll(params);
        return Result.succeed(list);
    }

    /**
     * 图片列表
     */
    @RequestMapping("/imageList")
    @PreAuthorize("hasAnyAuthority('sys_filefolder:sysfilefolder:list')")
    public Result imageList(@RequestParam Map<String, Object> params) {
        SysUser loginUser = SysUserUtil.getLoginAppUser();
        params.put("createUserid", loginUser.getId());
        params.put("status", 1);
        params.put("exts", Arrays.asList("jpg", "jpeg", "png", "gif", "bmp"));
        List<SysFileinfo> list = sysFileinfoService.findAll(params);
        return Result.succeed(list);
    }

    /**
     * 回收站
     */
    @RequestMapping("/recycledList")
    @PreAuthorize("hasAnyAuthority('sys_filefolder:sysfilefolder:list')")
    public Result recycledList(@RequestParam Map<String, Object> params) {
        SysUser loginUser = SysUserUtil.getLoginAppUser();
        params.put("createUserid", loginUser.getId());
        params.put("status", -1);
        params.remove("folderId");
        List<SysFileinfo> fileList = sysFileinfoService.findAll(params);
        return Result.succeed(fileList);
    }

    /**
     * 我的共享列表
     */
    @RequestMapping("/myShareList")
    @PreAuthorize("hasAnyAuthority('sys_filefolder:sysfilefolder:list')")
    public Result myShareList(@RequestParam Map<String, Object> params) {
        SysUser loginUser = SysUserUtil.getLoginAppUser();
        params.put("createUserid", loginUser.getId());
        params.put("status", 1);
        params.put("isShare", 1);
        if (params.containsKey("folderId") && StringUtils.isNotEmpty(params.get("folderId").toString())) {
            if (params.get("folderId").toString().equals("0")) {
                params.put("folderId", "");
            }
        } else {
            params.put("folderId", "");
        }
        List<SysFileinfo> fileList = sysFileinfoService.findAll(params);
        if (params.containsKey("folderId") && StringUtils.isNotEmpty(params.get("folderId").toString())) {
            params.put("parentId", params.get("folderId"));
            if (params.get("folderId").toString().equals("0")) {
                params.put("parentId", "");
            }
        } else {
            params.put("parentId", "");
        }
        List<SysFilefolder> folderList = sysFilefolderService.findAll(params);
        if (CollectionUtils.isNotEmpty(folderList)) {
            fileList.addAll(folderList.stream().map(item ->
                    {
                        SysFileinfo a = new SysFileinfo();
                        BeanUtils.copyProperties(item, a);
                        return a;
                    }
            ).collect(Collectors.toList()));
        }
        return Result.succeed(fileList);
    }


    /**
     * 他人共享列表
     */
    @RequestMapping("/otherShareList")
    @PreAuthorize("hasAnyAuthority('sys_filefolder:sysfilefolder:list')")
    public Result otherShareList(@RequestParam Map<String, Object> params) {
        SysUser loginUser = SysUserUtil.getLoginAppUser();
        params.put("isOther", 1);
        params.put("otherCreateUserid", loginUser.getId());
        params.put("status", 1);
        params.put("isShare", 1);
        if (params.containsKey("folderId") && StringUtils.isNotEmpty(params.get("folderId").toString())) {
            if (params.get("folderId").toString().equals("0")) {
                params.put("folderId", "");
            }
        } else {
            params.put("folderId", "");
        }
        List<SysFileinfo> fileList = sysFileinfoService.findAll(params);
        if (params.containsKey("folderId") && StringUtils.isNotEmpty(params.get("folderId").toString())) {
            params.put("parentId", params.get("folderId"));
            if (params.get("folderId").toString().equals("0")) {
                params.put("parentId", "");
            }
        } else {
            params.put("parentId", "");
        }
        List<SysFilefolder> folderList = sysFilefolderService.findAll(params);
        if (CollectionUtils.isNotEmpty(folderList)) {
            fileList.addAll(folderList.stream().map(item ->
                    {
                        SysFileinfo a = new SysFileinfo();
                        BeanUtils.copyProperties(item, a);
                        return a;
                    }
            ).collect(Collectors.toList()));
        }
        return Result.succeed(fileList);
    }

    /**
     * 查询单条记录
     */
    @RequestMapping("/findById")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:list')")
    public Result findById(String id) {
        return Result.succeed(sysFileinfoService.findById(id));
    }

    /**
     * 查询单条记录
     */
    @RequestMapping("/findByProcessId")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:list')")
    public Result findByProcessId(String processId) {
        return Result.succeed(sysFileinfoService.findById(processId));
    }

    /**
     * 保存
     */
    @RequestMapping("/saveOrUpdate")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:save')")
    @LogAnnotation(module = "文件", name = "发布")
    public Result save(@RequestBody @Valid SysFileinfo sysFileinfo, String keyValue) {
        if (StringUtils.isEmpty(keyValue)) {
            sysFileinfoService.save(sysFileinfo);
        } else {
            sysFileinfoService.update(sysFileinfo);
        }
        return Result.succeed("操作成功");
    }


    /**
     * 删除
     */
    @PostMapping("/delete/{id}")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:delete')")
    @LogAnnotation(module = "文件", name = "删除")
    public Result delete(@PathVariable String id, String fileType) {
        if (StringUtils.isNotEmpty(fileType) && fileType.equals("folder")) {
            sysFilefolderService.delete(id);
        } else {
            sysFileinfoService.delete(id);
        }

        return Result.succeed("删除成功");
    }

    /**
     * 还原
     */
    @PostMapping("/restore/{id}")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:restore')")
    @LogAnnotation(module = "文件", name = "还原")
    public Result restore(@PathVariable String id, String fileType) {
        if (StringUtils.isNotEmpty(fileType) && fileType.equals("folder")) {
            sysFilefolderService.restore(id);
        } else {
            sysFileinfoService.restore(id);
        }

        return Result.succeed("还原成功");
    }

    /**
     * 彻底删除
     */
    @PostMapping("/thoroughDelete/{id}")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:thoroughDelete')")
    @LogAnnotation(module = "文件", name = "彻底删除")
    public Result thoroughDelete(@PathVariable String id, String fileType) {
        if (StringUtils.isNotEmpty(fileType) && fileType.equals("folder")) {
            sysFilefolderService.thoroughDelete(id);
        } else {
            sysFileinfoService.thoroughDelete(id);
        }

        return Result.succeed("彻底删除成功");
    }

    /**
     * 清空回收站
     */
    @PostMapping("/emptyRecycled")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:emptyRecycled')")
    public Result emptyRecycled() {
        sysFilefolderService.emptyRecycled();
        sysFileinfoService.emptyRecycled();

        return Result.succeed("清空成功");
    }

    /**
     * 上传请求
     */
    @PostMapping("/upload")
    @ResponseBody
    public Result uploadFile(String folderId, MultipartFile file) {
        try {
            sysFileinfoService.upload(folderId, file);
            return Result.succeed("上传成功");
        } catch (Exception e) {
            log.error("上传文件失败[{}]", e.getMessage());
            return Result.failed("上传失败");
        }
    }

    /**
     * 下载请求
     */
    @PostMapping("/download")
    @ResponseBody
    public void downloadFile(String id, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        try {
            SysFile file = sysFileService.findById(id);
            String fileName = file.getName();
            String path = file.getUrl().substring(file.getUrl().indexOf("profile/") + 8);
            String realFileName = fileName.substring(fileName.lastIndexOf("/") + 1);
            String filePath = fileuploadPath + File.separator + path;

            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete != null && delete) {
                FileUtils.deleteFile(filePath);
            }
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 共享
     */
    @RequestMapping("/share/{id}")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:share')")
    public Result share(@PathVariable String id, @RequestBody @Valid List<SysFileinfoAuthorize> fileinfoAuthorizes, Integer isShare, String fileType) {
        if (StringUtils.isNotEmpty(fileType) && fileType.equals("folder")) {
            sysFilefolderService.share(id, fileinfoAuthorizes, isShare);
        } else {
            sysFileinfoService.share(id, fileinfoAuthorizes, isShare);
        }
        return Result.succeed("共享成功");
    }

    /**
     * 获取共享权限配置
     */
    @RequestMapping("/share/getPermission")
    public Result getSharePermission(String keyValue) {
        List<SysFileinfoAuthorize> result = sysFileinfoAuthorizeService.findByFileinfoId(keyValue);
        return Result.succeed(result);
    }

    /**
     * 保存
     */
    @RequestMapping("/move")
    @PreAuthorize("hasAnyAuthority('sys_fileinfo:sysfileinfo:move')")
    public Result move(String keyValue, String moveFolderId, String fileType) {
        if (StringUtils.isNotEmpty(fileType) && fileType.equals("folder")) {
            sysFilefolderService.move(keyValue, moveFolderId);
        } else {
            sysFileinfoService.move(keyValue, moveFolderId);
        }
        return Result.succeed("移动成功");
    }

    /**
     * 查询审核任务
     *
     * @param keyword
     * @param startTime
     * @param endTime
     * @param categoryId
     * @return
     */
    @GetMapping("/tasks")
    public PageResult findTasks(@RequestParam(value = "keyword", required = false) String keyword,
                            @RequestParam(value = "startTime", required = false)
                            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
                            @RequestParam(value = "endTime", required = false)
                            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime,
                            @RequestParam(value = "categoryId", required = false) String categoryId) {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();
        Map<String, Object> params = new HashMap<>();
        if (StringUtils.isNotEmpty(keyword)) {
            params.put("keyword", keyword);
        }
        params.put("startTime", startTime == null ? DateUtil.getFirstDayOfMonth(DateUtil.getYear(), DateUtil.getMonth()) : DateUtil.format(startTime));
        params.put("endTime", endTime == null ? DateUtil.getLastDayOfMonth(DateUtil.getYear(), DateUtil.getMonth()) : DateUtil.format(endTime));

        params.put("schemeCode", "bill_uploadfile");
        params.put("page", 1);
        params.put("limit", 20);
        PageResult<WFProcessinstance> processinstancePageResult = null;
        PageResult<FileAuthProcessDto> result = new PageResult<>();
        List<FileAuthProcessDto> dtoList = new ArrayList<>();
        switch (categoryId) {
            case "1":
                params.put("createUserid", loginUser.getId());
                processinstancePageResult = processinstanceService.pageProcessinstances(params);
                break;
            case "2":
                params.put("createUserid", loginUser.getId());
                processinstancePageResult = processinstanceService.pageActiveTasks(loginUser, params);
                break;
            case "3":
                processinstancePageResult = processinstanceService.pageFinishedTasks(loginUser, params);
                break;
            default:
                processinstancePageResult = processinstanceService.pageProcessinstances(params);
        }
        processinstancePageResult.getData().forEach(item -> {
            FileAuthProcessDto dto = new FileAuthProcessDto();
            BeanUtils.copyProperties(item, dto);
            SysFileinfo fileinfo = sysFileinfoService.findById(item.getId());
            dto.setName(fileinfo != null ? fileinfo.getName() : "");
            dtoList.add(dto);
        });
        result.setData(dtoList);
        result.setCount(processinstancePageResult.getCount());
        result.setResp_code(processinstancePageResult.getResp_code());
        return result;
    }
}
